﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Windows.Forms;
using Relocation.Data;

namespace Relocation.Com.Tools
{
	public class Tools
	{
		/// <summary>
		/// 发送建议
		/// </summary>
		/// <param name="suggestMessage">建议信息</param>
		public static void SendSuggest(string suggestMessage)
		{
			try
			{
				MailMessage myMail = new MailMessage();
				myMail.From = new MailAddress("123@gmail.com");
				myMail.To.Add(new MailAddress("123@qq.com"));
				myMail.Subject = "建议（拆迁系统）--" + System.DateTime.Now.ToString("yy年MM月dd日");
				myMail.SubjectEncoding = Encoding.UTF8;
				myMail.Body = suggestMessage;

				//附件
				//myMail.Attachments.Add(new Attachment(this.text_fj.Text));

				myMail.BodyEncoding = Encoding.UTF8;
				myMail.IsBodyHtml = false;
				myMail.Priority = MailPriority.High;
				Tools.SendMail(myMail);
			} catch (Exception)
			{
				throw;
			}

		}


		/// <summary>
		///  发送邮件
		/// </summary>
		/// <param name="mailMessage">邮件对象</param>
		public static void SendMail(MailMessage mailMessage)
		{

			///用Gmail账户发邮件
			try
			{
				SmtpClient sender2 = new SmtpClient();
				sender2.Host = "smtp.gmail.com";
				sender2.Port = 587;
				sender2.Credentials = new NetworkCredential("123@gmail.com", "123");
				sender2.DeliveryMethod = SmtpDeliveryMethod.Network;
				sender2.EnableSsl = true;

				try
				{
					sender2.Send(mailMessage);
				} catch (Exception)
				{
					sender2.Port = 465;
					sender2.Send(mailMessage);
				}
			} catch (Exception)
			{
				throw;
			}

		}

		/// <summary>
		/// 得到deg文件的缩略图
		/// </summary>
		/// <param name="fileName"></param>
		/// <returns></returns>
		public static Image GetImageFromDwg(string fileName)
		{
			return ViewDWG.GetDwgImage(fileName);
		}

		/// <summary>
		/// 将制定文件显示在PictureBox中
		/// </summary>
		/// <param name="pictureBox"></param>
		/// <param name="fileName"></param>
		public static void ShowImage(System.Windows.Forms.PictureBox pictureBox, string fileName)
		{
			try
			{
				fileName = Tools.GetFullPath(fileName);
				string ExtensionName = Path.GetExtension(fileName);
				DateTime time = File.GetCreationTime(fileName);
				if (!File.Exists(fileName))
				{
					//文件未找到
					pictureBox.Image = Relocation.Com.Resource.pic_err;
				} else
				{
					if (ExtensionName.Equals(".dwg"))
					{
						//显示缩略图
						pictureBox.Image = GetImageFromDwg(fileName);
					} else
					{
						//普通图片
						pictureBox.ImageLocation = fileName;
					}
				}
			} catch (Exception)
			{
				//错误
				pictureBox.Image = Relocation.Com.Resource.pic_err;
			}




		}

		/// <summary>
		/// 删除文件及其上级目录
		/// </summary>
		/// <param name="FileName"></param>
		public static void DeleteFile_Directory(string fileName)
		{
			try
			{
				if (string.IsNullOrEmpty(fileName))
					return;
				fileName = Tools.GetFullPath(fileName);
				string dir = Path.GetDirectoryName(fileName);
				if (File.Exists(fileName))
					File.Delete(fileName);

				if (Directory.Exists(dir))
					Directory.Delete(dir);
			} catch (Exception)
			{
				throw;
			}
		}

		/// <summary>
		/// 获得程序当前的路径
		/// 此方法的主要目的是为了去除路径字符中最后一个反斜杠（如果盘符下根目录的话会出现自动增加反斜杠的情况）
		/// </summary>
		/// <returns>程序当前的路径</returns>
		public static string GetStartupPath()
		{
			if (!Application.StartupPath.EndsWith(@"\"))
			{
				return Application.StartupPath;
			} else
			{
				return Application.StartupPath.Remove(Application.StartupPath.Length - 1, 1);
			}

		}

		/// <summary>
		/// 将文件复制到目标位置（自动创建目录,默认覆盖同名文件）
		/// </summary>
		/// <param name="sourceFileName">原文件</param>
		/// <param name="destFileName">目标文件</param>
		public static void CopyFile(string sourceFileName, string destFileName)
		{
			CopyFile(sourceFileName, destFileName, true);
		}

		/// <summary>
		/// 将文件复制到目标 位置（自动创建目录）
		/// </summary>
		/// <param name="sourceFileName">原文件</param>
		/// <param name="destFileName">目标文件</param>
		/// <param name="overwrite">是否覆盖</param>
		public static void CopyFile(string sourceFileName, string destFileName, bool overwrite)
		{
			if (!File.Exists(sourceFileName))
				throw new Exception("原文件找不到！");
			string directory = Path.GetDirectoryName(destFileName);
			if (!Directory.Exists(directory))
				Directory.CreateDirectory(directory);
			File.Copy(sourceFileName, destFileName, overwrite);
		}

		/// <summary>
		/// 将文件保存到Docs文件夹，并返回新的文件地址（相对路径）
		/// </summary>
		/// <param name="fileName">原文件</param>
		/// <returns>新文件地址</returns>
		public static string SaveFileToDocs(string fileName)
		{
			string name = Path.GetFileName(fileName);
			string NewFileName = @"\docs\" + System.DateTime.Now.ToFileTime().ToString() + @"\" + name;
			Tools.CopyFile(fileName, Path.GetFullPath(NewFileName), true);
			return NewFileName;
		}

		/// <summary>
		/// 返回错误信息，如果包含实例对象则返回错误实例对象的信息（InnerException.Message）
		/// </summary>
		/// <param name="ex">Exception</param>
		/// <returns>Message</returns>
		public static string GetExceptionMessage(Exception ex)
		{
			if (ex == null)
				return "";
			if (ex.InnerException == null)
				return ex.Message;
			else
				return ex.InnerException.Message;

		}


		/// <summary>
		/// 浏览文件（打开）
		/// </summary>
		/// <param name="filePath">文件路径</param>
		public static void OpenFile(string filePath)
		{
			try
			{
				filePath = Tools.GetFullPath(filePath);
				if (File.Exists(filePath))
				{
					Process.Start(filePath);
				}
			} catch (Exception)
			{
				throw;
			}
			//else
			//{
			//      Log.Error("文件未找到，路径：" + filePath);
			//      throw new Exception("文件未找到");
			//}
		}

		/// <summary>
		/// 获取绝对路径（添加程序启动路径）
		/// </summary>
		/// <param name="path"></param>
		public static string GetFullPath(string path)
		{
			return Path.IsPathRooted(path) ? path : Path.GetFullPath(path);
		}

		/// <summary>
		/// 数据库还原
		/// </summary>
		/// <param name="objectContext">ObjectContext</param>
		/// <param name="filePath">备份文件路径</param>
		public static void DataRestore(string filePath)
		{
			DataModel objectContext = new DataModel();
			//判断文件是否存在
			if (!File.Exists(filePath))
				throw new Exception("备份数据库未找到!");
			//数据库名
			string DataBaseName = "RelocationServer";
			//构建恢复数据库的sql脚本
			string SqlString = @"use master;alter database " + DataBaseName + " set offline with rollback immediate;restore database " + DataBaseName + " from disk = '" + filePath + "'  with replace";

			using (objectContext)
			{
				var bindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
				var factoryProperty = typeof(System.Data.EntityClient.EntityConnection).GetProperty("StoreProviderFactory", bindingFlags);
				var factory = factoryProperty.GetValue(objectContext.Connection, null) as System.Data.Common.DbProviderFactory;
				var connStr = (objectContext.Connection as System.Data.EntityClient.EntityConnection).StoreConnection.ConnectionString;

				using (var conn = factory.CreateConnection())
				{
					conn.ConnectionString = connStr;
					conn.Open();
					try
					{
						var cmd = factory.CreateCommand();
						cmd.Connection = conn;
						cmd.CommandText = SqlString;
						cmd.ExecuteNonQuery();
						cmd.Dispose();
					} catch (Exception)
					{
						throw;
					} finally
					{
						conn.Close();
					}
				}
			}
		}

		/// <summary>
		/// 数据库备份
		/// </summary>
		/// <param name="objectContext">ObjectContext对象</param>
		/// <param name="filePath">目标文件路径</param>
		public static void DataBackup(string filePath)
		{
			try
			{
				DataModel objectContext = new DataModel();

				string directoryName = Path.GetDirectoryName(filePath);
				if (!Directory.Exists(directoryName))
					Directory.CreateDirectory(directoryName);

				if (File.Exists(filePath))
					File.Delete(filePath);

				string DataBaseName = "RelocationServer";

				string SqlString = @"BACKUP DATABASE " + DataBaseName + " TO DISK = '" + filePath + "'";

				using (objectContext)
				{
					var bindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;
					var factoryProperty = typeof(System.Data.EntityClient.EntityConnection).GetProperty("StoreProviderFactory", bindingFlags);
					var factory = factoryProperty.GetValue(objectContext.Connection, null) as System.Data.Common.DbProviderFactory;
					var connStr = (objectContext.Connection as System.Data.EntityClient.EntityConnection).StoreConnection.ConnectionString;

					using (var conn = factory.CreateConnection())
					{
						conn.ConnectionString = connStr;
						conn.Open();
						try
						{
							var cmd = factory.CreateCommand();
							cmd.Connection = conn;
							cmd.CommandText = SqlString;
							cmd.ExecuteNonQuery();
							cmd.Dispose();

						} catch (Exception ex)
						{
							throw new Exception("数据库备份错误：" + Tools.GetExceptionMessage(ex));
						} finally
						{
							conn.Close();
						}
					}
				}
			} catch (Exception)
			{
				throw;
			}

		}

		/// <summary>
		/// 执行SQL脚本文件
		/// </summary>
		/// <param name="sqlScriptFileName">sql脚本文件的路径</param>		
		public static void ExecSqlFile(string sqlScriptFileName)
		{
			try
			{
				if (!File.Exists(sqlScriptFileName))
					throw new Exception("Sql脚本未找到！");
				Process process = new Process();
				ProcessStartInfo processStartInfo = new ProcessStartInfo();
				processStartInfo.FileName = "osql";
				processStartInfo.Arguments = @" -E -S .\sqlexpress -d relocationserver -i " + "\"" + sqlScriptFileName + "\"";
				processStartInfo.CreateNoWindow = false;
				process.StartInfo = processStartInfo;
				process.Start();
				process.WaitForExit();
			} catch (Exception)
			{
				throw;
			}

		}

		#region 显示DWG缩略图
		class ViewDWG
		{
			struct BITMAPFILEHEADER
			{
				public short bfType;
				public int bfSize;
				public short bfReserved1;
				public short bfReserved2;
				public int bfOffBits;
			}
			public static Image GetDwgImage(string FileName)
			{
				if (!(File.Exists(FileName)))
				{
					throw new FileNotFoundException("文件没有被找到");
				}
				FileStream DwgF;  //文件流
				int PosSentinel;  //文件描述块的位置
				BinaryReader br;  //读取二进制文件
				int TypePreview;  //缩略图格式
				int PosBMP;       //缩略图位置 
				int LenBMP;       //缩略图大小
				short biBitCount; //缩略图比特深度 
				BITMAPFILEHEADER biH; //BMP文件头，DWG文件中不包含位图文件头，要自行加上去
				byte[] BMPInfo;       //包含在DWG文件中的BMP文件体
				MemoryStream BMPF = new MemoryStream(); //保存位图的内存文件流
				BinaryWriter bmpr = new BinaryWriter(BMPF); //写二进制文件类
				Image myImg = null;
				try
				{
					DwgF = new FileStream(FileName, FileMode.Open, FileAccess.Read);   //文件流
					br = new BinaryReader(DwgF);
					DwgF.Seek(13, SeekOrigin.Begin); //从第十三字节开始读取
					PosSentinel = br.ReadInt32();  //第13到17字节指示缩略图描述块的位置
					DwgF.Seek(PosSentinel + 30, SeekOrigin.Begin);  //将指针移到缩略图描述块的第31字节
					TypePreview = br.ReadByte();  //第31字节为缩略图格式信息，2 为BMP格式，3为WMF格式
					if (TypePreview == 1)
					{
					} else if (TypePreview == 2 || TypePreview == 3)
					{
						PosBMP = br.ReadInt32(); //DWG文件保存的位图所在位置
						LenBMP = br.ReadInt32(); //位图的大小
						DwgF.Seek(PosBMP + 14, SeekOrigin.Begin); //移动指针到位图块
						biBitCount = br.ReadInt16(); //读取比特深度
						DwgF.Seek(PosBMP, SeekOrigin.Begin); //从位图块开始处读取全部位图内容备用
						BMPInfo = br.ReadBytes(LenBMP); //不包含文件头的位图信息
						br.Close();
						DwgF.Close();
						biH.bfType = 19778; //建立位图文件头
						if (biBitCount < 9)
						{
							biH.bfSize = 54 + 4 * (int)(Math.Pow(2, biBitCount)) + LenBMP;
						} else
						{
							biH.bfSize = 54 + LenBMP;
						}
						biH.bfReserved1 = 0; //保留字节
						biH.bfReserved2 = 0; //保留字节
						biH.bfOffBits = 14 + 40 + 1024; //图像数据偏移
						//以下开始写入位图文件头
						bmpr.Write(biH.bfType); //文件类型
						bmpr.Write(biH.bfSize);  //文件大小
						bmpr.Write(biH.bfReserved1); //0
						bmpr.Write(biH.bfReserved2); //0
						bmpr.Write(biH.bfOffBits); //图像数据偏移
						bmpr.Write(BMPInfo); //写入位图
						BMPF.Seek(0, SeekOrigin.Begin); //指针移到文件开始处
						myImg = Image.FromStream(BMPF); //创建位图文件对象
						bmpr.Close();
						BMPF.Close();
					}
					return myImg;
				} catch (Exception ex)
				{
					throw new Exception(ex.Message);
				}
			}
		}
		#endregion


		#region 将数字转为汉字
		/// <summary> 
		/// 用于将一个数值型转化为汉语的读法. 
		/// </summary> 
		public class NumberToChn
		{
			public NumberToChn()
			{
				// 
				// TODO: 在此处添加构造函数逻辑 
				// 
			}

			/// <summary>
			/// decimal转为汉字
			/// </summary>
			/// <param name="dc">decimal</param>
			/// <param name="bUpper">汉字是否大写</param>
			/// <returns></returns>
			public static string GetChn(decimal dc, bool bUpper)
			{
				return GetChn(dc.ToString(), bUpper);
			}

			/// <summary>
			/// int转为汉字
			/// </summary>
			/// <param name="i">int</param>
			/// <param name="bUpper">汉字是否大写</param>
			/// <returns></returns>
			public static string GetChn(int i, bool bUpper)
			{
				return GetChn(i.ToString(), bUpper);
			}

			/// <summary>
			/// long转为汉字
			/// </summary>
			/// <param name="l">long</param>
			/// <param name="bUpper">汉字是否大写</param>
			/// <returns></returns>
			public static string GetChn(long l, bool bUpper)
			{
				return GetChn(l.ToString(), bUpper);
			}

			/// <summary>
			/// 将数字转为金额
			/// </summary>
			/// <param name="sDigital"></param>
			/// <param name="bUpper"></param>
			/// <returns></returns>
			public static string GetRMBChn(string sDigital, bool bUpper)
			{
				// 找出第一个点所在的位置，之前的部分用getchn来处理，之后的部分自已处理． 
				if (sDigital == null | sDigital.Length == 0)
					return "";

				int iIndex = sDigital.IndexOf(".");
				string sIntPart;
				string sDecPart;
				if (iIndex == -1)
				{
					sIntPart = sDigital;
					sDecPart = "";
				} else
				{
					sIntPart = sDigital.Substring(0, iIndex);
					sDecPart = sDigital.Substring(iIndex + 1);
				}

				StringBuilder sb = new StringBuilder(sDigital.Length * 2 + 10);
				foreach (char c in sDecPart)
				{
					if (char.IsDigit(c))
					{
						sb.Append(c);
					}
				}
				sDecPart = sb.ToString();
				sb.Length = 0;

				string sTmp = GetChn(sIntPart, bUpper);
				if (sTmp != "零" && sTmp.Length != 0)
				{
					sb.Append(sTmp);
					sb.Append(bUpper ? '园' : '元');
				}

				bool bPrevIsZero = false;
				if (sIntPart.Length > 0 && sIntPart.EndsWith("0") && sb.Length > 1)
				{
					bPrevIsZero = true;
				}
				for (int i = 0; i < sDecPart.Length && i < arRMBRight.Length; i++)
				{
					if (sDecPart[i] == '0')
					{
						bPrevIsZero = true;
					} else
					{
						if (bPrevIsZero == true)
						{
							sb.Append('零');
							bPrevIsZero = false;
						}
						sb.Append(bUpper ? arDigitals2[sDecPart[i] - '0'] : arDigitals[sDecPart[i] - '0']);
						sb.Append(arRMBRight[i]);
					}
				}
				if (sb.Length > 0)
				{
					sb.Append('整');
				} else
				{
					sb.Append(bUpper ? "零园整" : "零元整");
				}
				return sb.ToString();
			}

			/// <summary>
			/// 数字转换汉字
			/// </summary>
			/// <param name="Session">需转换的字串</param>
			/// <param name="bUpper">true为大写汉字false为小写汉字</param>
			/// <returns>string</returns>
			public static string GetChn(string s, bool bUpper)
			{
				// 先将s过滤，删除所有的非数字字符。 
				if (s == null || s.Trim().Length == 0)
					return "";
				StringBuilder sb = new StringBuilder(s.Length);
				int iPointCount = 0;
				for (int i = 0; i < s.Length; i++)
				{
					char c = s[i];
					if (Char.IsDigit(c))
					{
						sb.Append(c);
					} else if (c == '.')
					{
						// 如果是第二个之后的点，那么不管了。 
						if (iPointCount == 0)
						{
							sb.Append(c);
							iPointCount++;
						}
					} else if (c == '-' && i == 0)
					{
						sb.Append(c);
					} else
					{
						// 省下的全部忽略 
					}
				}

				string sDigital = sb.ToString();
				if (sDigital.EndsWith("."))
				{
					sDigital = sDigital.Substring(0, sDigital.Length - 1);
				}
				if (sDigital.Length == 0)
				{
					sDigital = "0";
				}

				sb.Length = 0; // 留为后用。 

				// 从小数点前后分为两部分 
				int iTmp = sDigital.IndexOf('.');
				string sIntPart;
				string sDecimalPart;
				if (iTmp == -1)
				{
					sIntPart = sDigital;
					sDecimalPart = "";
				} else
				{
					sIntPart = sDigital.Substring(0, iTmp);
					sDecimalPart = sDigital.Substring(iTmp + 1);
				}

				// 处理小数点之前的部分 

				// 先决定最高位是什么位，再依次地向后拼出。 
				// 大循环是亿的个数， 小循环是万的个数。 

				sb = new StringBuilder(sDigital.Length * 2 + 6);
				if (sDigital.StartsWith("-"))
				{
					sb.Append("负");
					sIntPart = sIntPart.Substring(1);
				}
				// 如果小数点之后没有内容，之前部分又是空，那么不输出． 
				if (sIntPart.Length == 0 && sDecimalPart.Length == 0)
				{
					return "";
				}

				int iBitCntInWan = 0;
				bool bPrevIs0 = false;
				int iWanNotZeroCnt = 0;
				int iNotZeroCnt = 0;

				for (int i = 0; i < sIntPart.Length; i++)
				{
					int iBitCnt = sIntPart.Length - i - 1;

					char cNum = sIntPart[i];
					if (cNum == '0')
					{
						// 如果是零，那么不处理 
						bPrevIs0 = true;
					} else
					{
						if (bPrevIs0)
						{
							// 如果上一个是０ 
							if (iNotZeroCnt > 0)
							{
								//如果不是第一个字 那么加一个零字                                     
								sb.Append(bUpper ? arDigitals2[0] : arDigitals[0]);
							}
						}
						iWanNotZeroCnt++;
						iNotZeroCnt++;

						bPrevIs0 = false;
						sb.Append(bUpper ? arDigitals2[cNum - '0'] : arDigitals[cNum - '0']);    // 加数名 
						iBitCntInWan = iBitCnt % 4;
						if (iBitCntInWan != 0)
						{
							sb.Append(bUpper ? arRights2[iBitCntInWan] : arRights[iBitCntInWan]);    // 加权名 
						}
					}

					if (iBitCnt % 8 == 0)
					{
						// 遇亿的处理 
						if (iBitCnt / 8 >= 1 && iNotZeroCnt > 0)
							sb.Append('亿');
						bPrevIs0 = false;
						iWanNotZeroCnt = 0;
					} else if (iBitCnt % 4 == 0)
					{
						// 遇万位的处理 
						if ((iBitCnt % 8) / 4 >= 1 && iWanNotZeroCnt > 0)
						{
							sb.Append('万');
						}
						bPrevIs0 = false;
						iWanNotZeroCnt = 0;
					}
				}


				// 如果全部都是０，那么输出一个”零”． 
				if (iNotZeroCnt == 0)
				{
					sb.Append("零");
				}

				// 处理小数点之后的部分 
				if (sDecimalPart.Length != 0)
				{
					sb.Append("点");
					for (int i = 0; i < sDecimalPart.Length; i++)
					{
						sb.Append(bUpper ? arDigitals2[sDecimalPart[i] - '0'] : arDigitals[sDecimalPart[i] - '0']);
					}
				}
				iTmp = 0;
				if (sb[0] == '负')
				{
					iTmp = 1;
				}

				// 把起头的”一十”改为”拾”． 
				if (sb.Length >= 2)
				{
					if (sb[iTmp] == (bUpper ? arDigitals2[1] : arDigitals[1]) &&
					 sb[iTmp + 1] == (bUpper ? arRights2[1] : arRights[1]))
					{
						sb.Remove(iTmp, 1);
					}
				}
				return sb.ToString();
			}

			private static char[] arRights = { ' ', '十', '百', '千' }; // 权名 
			private static char[] arRights2 = { ' ', '拾', '佰', '仟' }; // 权名 

			private static char[] arDigitals = { 
            '零','一','二','三','四','五','六','七','八','九' 
           };
			private static char[] arDigitals2 = { 
            '零','壹','贰','叁','肆','伍','陆','柒','捌','玖' 
           };

			private static char[] arRMBRight = { '角', '分', '厘', '毫', '丝' };

		}
		#endregion

	}
}
